import { App, Button, Tabs, TabsProps, Empty, Drawer, Spin } from 'antd'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
import { useState, useEffect, useRef, useReducer } from 'react'
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import {
  SummaryPieData,
  SearchBody,
  PieData,
  MonitorApiData,
  MonitorSubscriberData,
  InvokeData,
  MessageData
} from '@dashboard/const/type'
import { getTime, getTimeUnit, changeNumberUnit } from '../utils/dashboard'
import ScrollableSection from '@common/components/aoplatform/ScrollableSection'
import { RangeValue, TimeRange } from '@common/components/aoplatform/TimeRangeSelector'
import TimeRangeSelector from '@common/components/aoplatform/TimeRangeSelector'
import MonitorLineGraph from './MonitorLineGraph'
import MonitorPieGraph from './MonitorPieGraph'
import MonitorTable, { MonitorTableHandler } from './MonitorTable'
import { CloseOutlined, ExpandOutlined, LoadingOutlined } from '@ant-design/icons'
import DashboardDetail from '@dashboard/pages/DashboardDetail'
import { $t } from '@common/locales'

dayjs.extend(customParseFormat)

export type MonitorTotalPageProps = {
  fetchPieData: (body: SearchBody) => Promise<BasicResponse<PieData>>
  fetchInvokeData: (body: SearchBody) => Promise<BasicResponse<InvokeData>>
  fetchMessageData: (body: SearchBody) => Promise<BasicResponse<MessageData>>
  fetchTableData: (
    body: SearchBody,
    type: 'api' | 'subscriber' | 'provider'
  ) => Promise<BasicResponse<{ top10: MonitorApiData[] | MonitorSubscriberData[] }>>
  goToDetail: (body: SearchBody, val: MonitorApiData | MonitorSubscriberData, type: string) => void
}

const ACTIONS = {
  REQUEST_COMPLETE: 'REQUEST_COMPLETE',
  RESET: 'RESET'
}

const initialState = {
  getPieData: false,
  getInvokeData: false,
  getMessageData: false,
  getTablesData: false
}

function reducer(state: typeof initialState, action: { type: string; payload?: string }) {
  switch (action.type) {
    case ACTIONS.REQUEST_COMPLETE:
      return { ...state, [action.payload!]: true }
    case ACTIONS.RESET:
      return initialState
    default:
      return state
  }
}

const MonitorTotalPage = (props: MonitorTotalPageProps) => {
  const { fetchPieData, fetchInvokeData, fetchMessageData, fetchTableData } = props
  const { message } = App.useApp()
  const [queryData, setQueryData] = useState<SearchBody>()
  const [timeButton, setTimeButton] = useState<'' | 'hour' | 'day' | 'threeDays' | 'sevenDays'>('hour')
  const [datePickerValue, setDatePickerValue] = useState<RangeValue>()
  const [requestStatic, setRequestStatic] = useState<SummaryPieData>()
  const [proxyStatic, setProxyStatic] = useState<SummaryPieData>()
  const [requestPie, setRequestPie] = useState<{ [key: string]: number }>({})
  const [proxyPie, setProxyPie] = useState<{ [key: string]: number }>({})
  const [requestSucRate, setRequestSucRate] = useState<string>('0%')
  const [proxySucRate, setProxySucRate] = useState<string>('0%')
  const [invokeStatic, setInvokeStatic] = useState<InvokeData>({
    date: [],
    requestRate: [],
    requestTotal: [],
    proxyRate: [],
    proxyTotal: [],
    status_4xx: [],
    status_5xx: []
  })
  const [trafficStatic, setTrafficStatic] = useState<MessageData>({ date: [], requestMessage: [], responseMessage: [] })
  const [pieError, setPieError] = useState<boolean>(false)
  const [invokeStaticError, setInvokeStaticError] = useState<boolean>(false)
  const [trafficStaticError, setTrafficStaticError] = useState<boolean>(false)
  const [timeUnit, setTimeUnit] = useState<string>()
  const monitorApiTableRef = useRef<MonitorTableHandler>(null)
  const monitorSubTableRef = useRef<MonitorTableHandler>(null)
  const [detailEntityName, setDetailEntityName] = useState<string>('')
  const [detailType, setDetailType] = useState<'api' | 'provider' | 'subscriber'>()
  const [drawerOpen, setDrawerOpen] = useState<boolean>(false)
  const [detailId, setDetailId] = useState<string>()
  const [fullScreen, setFullScreen] = useState<boolean>(false)
  const [recordQuery, setRecordQuery] = useState<
    SearchBody & { timeButton: '' | 'hour' | 'day' | 'threeDays' | 'sevenDays' }
  >()
  const [queryBtnLoading, setQueryBtnLoading] = useState<boolean>(false)
  const [totalEmpty, setTotalEmpty] = useState<boolean>(false)
  const [requestStatus, dispatch] = useReducer(reducer, initialState)

  useEffect(() => {
    const isLoading = Object.values(requestStatus).every((status) => status !== true)
    setQueryBtnLoading(isLoading)
  }, [requestStatus])

  useEffect(() => {
    getMonitorData()
  }, [])

  const getMonitorData = () => {
    // setTotalEmpty(true)
    dispatch({ type: ACTIONS.RESET })
    // ...根据时间和集群获取监控数据...
    let query = queryData
    if (!queryData || queryData.start === undefined) {
      const { startTime, endTime } = getTime(timeButton, datePickerValue || [])
      query = { ...query, start: startTime, end: endTime }
    }
    const data: SearchBody = query!
    setQueryData(data)
    setRecordQuery({ ...data, timeButton })
    getPieData(data)
    getInvokeData(data)
    getMessageData(data)
    monitorApiTableRef.current?.reload()
    monitorSubTableRef.current?.reload()
  }

  const getPieData = (body: SearchBody) => {
    fetchPieData(body)
      .then((resp) => {
        const { code, data, msg } = resp
        setQueryBtnLoading(false)
        if (code === STATUS_CODE.SUCCESS) {
          setPieError(false)
          setRequestStatic(data.requestSummary)
          setProxyStatic(data.proxySummary)
          setRequestPie({ ['请求成功数']: data.requestSummary.success, ['请求失败数']: data.requestSummary.fail })
          setProxyPie({ ['转发成功数']: data.proxySummary.success, ['转发失败数']: data.proxySummary.fail })
          setPieError(false)
          // this.requestPieRef?.changePieChart()
          // this.proxyPieRef?.changePieChart()
          setRequestSucRate(
            data.requestSummary.total === 0
              ? '0%'
              : ((data.requestSummary.success * 100) / data.requestSummary.total).toFixed(2) + '%'
          )
          setProxySucRate(
            data.proxySummary.total === 0
              ? '0%'
              : ((data.proxySummary.success * 100) / data.proxySummary.total).toFixed(2) + '%'
          )
          // setTotalEmpty(data.requestSummary.total === 0 && data.proxySummary.total === 0)
        } else {
          setPieError(true)
          message.error(msg || $t(RESPONSE_TIPS.dataError))
        }
      })
      .finally(() => {
        dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getPieData' })
      })
  }

  const getInvokeData = (body: SearchBody) => {
    fetchInvokeData(body)
      .then((resp) => {
        const { code, data, msg } = resp
        setQueryBtnLoading(false)
        if (code === STATUS_CODE.SUCCESS) {
          const { timeInterval, ...arr } = data
          setInvokeStatic(arr as InvokeData)
          setInvokeStaticError(false)
          setTimeUnit(getTimeUnit(timeInterval!))
          // this.invokeLineRef?.changeLineChart()
        } else {
          setInvokeStaticError(true)
          message.error(msg || $t(RESPONSE_TIPS.dataError))
        }
      })
      .finally(() => {
        dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getInvokeData' })
      })
  }

  const getMessageData = (body: SearchBody) => {
    fetchMessageData(body)
      .then((resp) => {
        const { code, data, msg } = resp
        setQueryBtnLoading(false)
        if (code === STATUS_CODE.SUCCESS) {
          setTrafficStaticError(false)
          setTrafficStatic(data)
          // this.trafficLineRef?.changeLineChart()
        } else {
          setTrafficStaticError(true)
          message.error(msg || $t(RESPONSE_TIPS.dataError))
        }
      })
      .finally(() => {
        dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getMessageData' })
      })
  }

  const getTablesData = (body: SearchBody, type: 'api' | 'subscriber' | 'provider') => {
    return fetchTableData(body, type)
      .then((resp) => {
        const { code, data, msg } = resp
        setQueryBtnLoading(false)
        if (code === STATUS_CODE.SUCCESS) {
          return {
            data: data.top10.map((x: MonitorApiData | MonitorSubscriberData) => {
              x.proxyRate = Number((x.proxyRate * 100).toFixed(2))
              x.requestRate = Number((x.requestRate * 100).toFixed(2))
              return x
            }),
            success: true
          }
        } else {
          message.error(msg || $t(RESPONSE_TIPS.dataError))
          return { data: [], success: false }
        }
      })
      .catch(() => {
        setQueryBtnLoading(false)
        return { data: [], success: false }
      })
      .finally(() => {
        dispatch({ type: ACTIONS.REQUEST_COMPLETE, payload: 'getTablesData' })
      })
  }

  const resetQuery = () => {
    // ...重置查询条件...
    setTimeButton('hour')
    setDatePickerValue(null)
    setQueryData(undefined)
  }

  const handleTimeRangeChange = (timeRange: TimeRange) => {
    setQueryData((pre) => ({ ...pre, ...timeRange }) as SearchBody)
  }

  const monitorTopDataTabItems: TabsProps['items'] = [
    {
      label: $t('API 请求量 Top10'),
      key: 'api',
      children: (
        <MonitorTable
          className="py-[10px]"
          ref={monitorApiTableRef}
          type="api"
          id="dashboard_top10_api"
          onRowClick={(record) => {
            getDetailData(record as MonitorApiData, 'api')
          }}
          request={() => getTablesData(queryData || {}, 'api')}
        />
      )
    },
    {
      label: $t('消费者调用量 Top10'),
      key: 'subscribers',
      children: (
        <MonitorTable
          className="py-[10px]"
          ref={monitorSubTableRef}
          type="subscribers"
          id="dashboard_top10_subscriber"
          onRowClick={(record) => {
            getDetailData(record as MonitorSubscriberData, 'subscriber')
          }}
          request={() => getTablesData(queryData || {}, 'subscriber')}
        />
      )
    },
    {
      label: $t('服务被调用量 Top10'),
      key: 'providers',
      children: (
        <MonitorTable
          className="py-[10px]"
          ref={monitorSubTableRef}
          type="provider"
          id="dashboard_top10_provider"
          onRowClick={(record) => {
            getDetailData(record as MonitorSubscriberData, 'provider')
          }}
          request={() => getTablesData(queryData || {}, 'provider')}
        />
      )
    }
  ]

  const getDetailData = (entity: MonitorApiData | MonitorSubscriberData, type: 'api' | 'provider' | 'subscriber') => {
    setDetailEntityName(entity.name)
    setDetailId(entity.id)
    setDetailType(type)
    setDrawerOpen(true)
  }

  return (
    <div className={`h-full overflow-hidden pb-btnybase flex flex-col  bg-[#fff] `}>
      <ScrollableSection>
        <div className="flex items-center flex-wrap pb-[10px] px-btnbase content-before bg-MAIN_BG pr-PAGE_INSIDE_X  ">
          <TimeRangeSelector
            labelSize="small"
            initialTimeButton={timeButton}
            onTimeButtonChange={setTimeButton}
            initialDatePickerValue={datePickerValue}
            onTimeRangeChange={handleTimeRangeChange}
          />
          <div className="flex flex-nowrap items-center  pt-btnybase">
            <Button onClick={resetQuery}>{$t('重置')}</Button>
            <Button
              className="ml-btnybase"
              type="primary"
              loading={queryBtnLoading}
              onClick={() => {
                getMonitorData()
                setQueryBtnLoading(true)
              }}
            >
              {$t('查询')}
            </Button>
          </div>
        </div>
        <Spin
          wrapperClassName={`flex-1 ${totalEmpty ? '' : 'overflow-auto'}`}
          indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />}
          spinning={queryBtnLoading}
        >
          {totalEmpty ? (
            <Empty className="mt-[100px]" image={Empty.PRESENTED_IMAGE_SIMPLE} />
          ) : (
            <div className=" h-full scroll-area pr-PAGE_INSIDE_X ">
              {/* 图表区域 */}
              <div
                className=" px-btnbase  mt-[12px] mb-[16px] grid gap-[20px]"
                style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(570px, 1fr))' }}
              >
                {/* 请求统计饼图 */}
                {pieError ? (
                  <Empty
                    className="pt-[80px] bg-MAIN_BG  w-[50%] h-[200px]  m-0 mr-[16px]"
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    description={$t('暂无请求统计数据')}
                  />
                ) : (
                  <MonitorPieGraph
                    className="bg-MAIN_BG border-[1px] border-solid border-BORDER rounded-[10px]"
                    title={$t('请求统计')}
                    pieData={requestPie}
                    labelName={$t('请求成功率')}
                    labelValue={requestSucRate}
                    subText={$t('请求总数')}
                    subValue={
                      changeNumberUnit(requestStatic?.total).value + $t(changeNumberUnit(requestStatic?.total).unit)
                    }
                    status4xxCount={requestStatic?.status_4xx}
                    status5xxCount={requestStatic?.status_5xx}
                  />
                )}
                {/* 转发统计饼图 */}
                {pieError ? (
                  <Empty
                    className="pt-[80px] bg-MAIN_BG w-[50%] h-[200px] m-0"
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    description={$t('暂无转发统计数据')}
                  />
                ) : (
                  <MonitorPieGraph
                    className=" bg-MAIN_BG border-[1px] border-solid border-BORDER rounded-[10px]"
                    title={$t('转发统计')}
                    pieData={proxyPie}
                    labelName={$t('转发成功率')}
                    labelValue={proxySucRate}
                    subText={$t('转发总数')}
                    subValue={`${changeNumberUnit(proxyStatic?.total).value}  ${$t(changeNumberUnit(proxyStatic?.total).unit)}`}
                    status4xxCount={proxyStatic?.status_4xx}
                    status5xxCount={proxyStatic?.status_5xx}
                  />
                )}
              </div>
              {/* 折线图区域 */}
              <div
                className=" px-btnbase  mt-[12px] mb-[16px] grid gap-[20px]"
                style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(570px, 1fr))' }}
              >
                {/* 调用量统计折线图 */}
                {invokeStaticError ? (
                  <Empty
                    className="pt-[80px]  mb-[16px] h-[200px] bg-MAIN_BG"
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    description={$t('暂无调用量统计数据')}
                  />
                ) : (
                  <MonitorLineGraph
                    className=" bg-MAIN_BG pt-[16px] border-[1px] border-solid border-BORDER rounded-[10px]"
                    lineData={invokeStatic}
                    titles={[$t('调用量统计')]}
                    yAxisTitle={$t(timeUnit || '-')}
                    type="invoke"
                  />
                )}
                {/* 报文量统计折线图 */}
                {trafficStaticError ? (
                  <Empty
                    className=" bg-MAIN_BG pt-[80px]  mb-0 h-[200px]"
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                    description={$t('暂无报文量统计数据')}
                  />
                ) : (
                  <MonitorLineGraph
                    className=" bg-MAIN_BG pt-[16px] border-[1px] border-solid border-BORDER rounded-[10px]"
                    lineData={trafficStatic}
                    titles={[$t('报文量统计')]}
                    yAxisTitle={$t(timeUnit || '-')}
                    type="traffic"
                  />
                )}
              </div>
              {/* 表格区域 */}
              <div className="bg-MAIN_BG pt-[4px] m-btnbase mt-[16px] rounded">
                <Tabs
                  defaultActiveKey={'total'}
                  items={monitorTopDataTabItems}
                  destroyInactiveTabPane={true}
                  className="h-auto mt-[4px] not-top-border-table not-top-padding-table mx-[12px]"
                  size="small"
                  tabBarStyle={{ paddingLeft: '10px', marginTop: '0px', marginBottom: '0px' }}
                />
                <Drawer
                  destroyOnClose={true}
                  maskClosable={false}
                  className={fullScreen ? 'h-calc-100vh-minus-navbar mt-navbar-height' : ''}
                  mask={!fullScreen}
                  title={
                    <>
                      {fullScreen && (
                        <a
                          className="mr-btnrbase text-[14px]"
                          onClick={() => {
                            setFullScreen(false)
                          }}
                        >
                          <CloseOutlined className="mr-[4px]" />
                          {$t('退出全屏')}
                        </a>
                      )}
                      <span className="mr-btnrbase">
                        {detailEntityName}
                        {$t('调用详情')}
                      </span>
                      {!fullScreen && (
                        <ExpandOutlined
                          className="text-MAIN_TEXT hover:text-MAIN_HOVER_TEXT"
                          onClick={() => {
                            setFullScreen(true)
                          }}
                        />
                      )}
                    </>
                  }
                  width={fullScreen ? '100%' : '60%'}
                  onClose={() => setDrawerOpen(false)}
                  open={drawerOpen}
                >
                  <DashboardDetail
                    fullScreen={fullScreen}
                    name={detailEntityName!}
                    queryData={recordQuery!}
                    dashboardDetailId={detailId!}
                    dashboardType={detailType as 'api' | 'subscriber'}
                  />
                </Drawer>
              </div>
            </div>
          )}
        </Spin>
      </ScrollableSection>
    </div>
  )
}
export default MonitorTotalPage
